﻿using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using MqttSample.Business;

namespace MqttSample
{
    /// <summary>
    /// mqtt service
    /// </summary>
    public class MqttHostedService : IHostedService
    {
        private IOptionsMonitor<List<MqttClientOption>> _mqttClientOption;
        private IMultiMqttClientWrapper _multiWrapper;
        private ExecuteBusinessData _execBusiness;
        /// <summary>
        /// ctor
        /// </summary>
        public MqttHostedService(IOptionsMonitor<List<MqttClientOption>> mqttClientOption)
        {
            _mqttClientOption = mqttClientOption;
            _execBusiness = new ExecuteBusinessData();
            DataChannelWrapper.Instance.Init(1);
            DataChannelWrapper.Instance.ReadEvent += DataChannelReadEvent;
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            _multiWrapper = new MultiMqttClientWrapper(_mqttClientOption.CurrentValue?.ToArray());
            _multiWrapper.MultiOutEventData += MultiOutEventData;
            await _multiWrapper.StartClientAsync();
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            _multiWrapper.Dispose();
            DataChannelWrapper.Instance.Dispose();
            _execBusiness.Dispose();
            await Task.CompletedTask;
        }

        #region private methods
        private async void MultiOutEventData(MqttClientOption arg1, CallbackData arg2)
        {
            if (arg2.Type != DataType.Subscribe)
            {
                Console.WriteLine($"{arg2.Time:yyyy-MM-dd HH:mm:ss：}mqtt:{arg2.Type}_{arg2.Message}");
            }
            else
            {
                Console.WriteLine($"{arg2.Time:yyyy-MM-dd HH:mm:ss：}mqtt:{arg2.Type}_{arg2.CurrentClientId}_{arg2.Topic}");
                if (arg1.IsConsoleLog)
                {
                    Console.WriteLine($"{arg2.Time:yyyy-MM-dd HH:mm:ss：}->{BitConverter.ToString(arg2.Data)}");
                }
                await DataChannelWrapper.Instance.WriteAsync(arg1, arg2);
            }
        }

        private async void DataChannelReadEvent(MqttClientOption arg1, CallbackData arg2)
        {
            await _execBusiness.ExecuteAsync(arg1, arg2);
        }
        #endregion
    }   
}
